#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
TCP协议实现
基于现有的lis_client_自有协议_unified_tcp.py实现
"""

import socket
import threading
import time
import logging
import re
import struct
import os
import base64
import json
from enum import Enum
from datetime import datetime
from typing import Optional, Callable
from queue import Queue, Full, Empty
from PyQt6.QtCore import QThread, pyqtSignal

logger = logging.getLogger(__name__)

class ProtocolType(Enum):
    UNKNOWN = 0
    CUSTOM_LIS = 1

class AnalysisMode(Enum):
    """分析模式枚举"""
    UNKNOWN = 0
    NORMAL = 1          # 常规模式
    VARIANT_THAL = 2    # 变异/地贫模式
    FAST_VARIANT = 3    # 快速变异模式

class ImageProcessor:
    """图片处理器 - 支持十六进制和base64格式"""
    
    @staticmethod
    def save_hex_image(hex_data, filename, images_dir='images'):
        """保存十六进制图片数据"""
        try:
            # 创建images目录
            if not os.path.exists(images_dir):
                os.makedirs(images_dir)
            
            # 清理十六进制数据（移除换行符和空格）
            clean_hex_data = hex_data.replace('\n', '').replace('\r', '').replace(' ', '')
            
            # 将十六进制字符串转换为二进制数据
            img_bytes = bytes.fromhex(clean_hex_data)
            
            # 保存图片文件
            image_path = os.path.join(images_dir, filename)
            with open(image_path, 'wb') as f:
                f.write(img_bytes)
            
            return {
                'path': image_path,
                'size': len(img_bytes),
                'hex_length': len(clean_hex_data),
                'format': 'hex_to_binary',
                'saved': True
            }
                
        except Exception as e:
            logger.error(f"保存十六进制图片失败: {e}")
            return {
                'saved': False,
                'error': str(e),
                'format': 'hex_to_binary'
            }

    @staticmethod
    def save_base64_image(base64_data, filename, images_dir='images'):
        """保存base64图片数据"""
        try:
            # 创建images目录
            if not os.path.exists(images_dir):
                os.makedirs(images_dir)
            
            # 清理base64数据（移除换行符和空格）
            clean_data = base64_data.replace('\n', '').replace('\r', '').replace(' ', '')
            
            # 解码base64数据
            img_bytes = base64.b64decode(clean_data)
            
            # 保存图片文件
            image_path = os.path.join(images_dir, filename)
            with open(image_path, 'wb') as f:
                f.write(img_bytes)
            
            return {
                'path': image_path,
                'size': len(img_bytes),
                'base64_length': len(clean_data),
                'format': 'base64_to_binary',
                'saved': True
            }
                
        except Exception as e:
            logger.error(f"保存base64图片失败: {e}")
            return {
                'saved': False,
                'error': str(e),
                'format': 'base64_to_binary'
            }

    @staticmethod
    def detect_and_save_image(image_data, filename, images_dir='images'):
        """自动检测图片格式并保存"""
        try:
            # 清理数据
            clean_data = image_data.replace('\n', '').replace('\r', '').replace(' ', '')
            
            # 尝试检测格式
            # 检查是否为十六进制格式（只包含0-9, a-f, A-F）
            if re.match(r'^[0-9a-fA-F]+$', clean_data):
                logger.info(f"检测到十六进制格式图片数据，长度: {len(clean_data)}")
                return ImageProcessor.save_hex_image(clean_data, filename, images_dir)
            
            # 检查是否为base64格式（包含字母、数字、+、/、=）
            elif re.match(r'^[A-Za-z0-9+/=]+$', clean_data):
                logger.info(f"检测到base64格式图片数据，长度: {len(clean_data)}")
                return ImageProcessor.save_base64_image(clean_data, filename, images_dir)
            
            else:
                # 尝试作为base64处理（可能包含其他字符）
                logger.info(f"未知格式，尝试作为base64处理，长度: {len(clean_data)}")
                return ImageProcessor.save_base64_image(clean_data, filename, images_dir)
                
        except Exception as e:
            logger.error(f"图片格式检测和保存失败: {e}")
            return {
                'saved': False,
                'error': str(e),
                'format': 'unknown'
            }

class CustomLISParser:
    """自定义LIS协议解析器"""

    @staticmethod
    def detect_analysis_mode(results_str):
        """检测分析模式"""
        # 解析结果字符串，提取字段名
        pattern = r'([a-zA-Z][a-zA-Z0-9\-_]*)\|'
        detected_fields = set(re.findall(pattern, results_str))
        
        # 模式判断逻辑（基于实际数据优化）
        if 'v-win' in detected_fields:
            # 快速变异模式：包含v-win字段
            return AnalysisMode.FAST_VARIANT, "快速变异模式"
        elif 'A2' in detected_fields or 'HbE' in detected_fields or 'HbD' in detected_fields or 'HbS' in detected_fields or 'HbC' in detected_fields:
            # 变异/地贫模式：包含A2、HbE、HbD、HbS、HbC等变异筛查字段
            return AnalysisMode.VARIANT_THAL, "变异/地贫模式"
        elif 'p3' in detected_fields:
            # 如果包含p3但没有变异筛查字段，可能是快速变异模式的简化版本
            return AnalysisMode.FAST_VARIANT, "快速变异模式"
        else:
            # 常规模式：仅包含基础组分，不包含变异筛查字段和p3
            return AnalysisMode.NORMAL, "常规模式"

    @staticmethod
    def parse_results_by_mode(results_str, mode):
        """根据模式解析结果数据"""
        results = {}
        
        if mode == AnalysisMode.NORMAL:
            # 常规模式：基础组分（7项）
            pattern = r'([a-zA-Z0-9\-_]+)\|([0-9.]+)'
            matches = re.findall(pattern, results_str)
            for key, value in matches:
                results[key] = value
                
        elif mode == AnalysisMode.VARIANT_THAL:
            # 变异/地贫模式：扩展至14项，包含变异筛查字段
            pattern = r'([a-zA-Z0-9\-_]+)\|([0-9.]+)'
            matches = re.findall(pattern, results_str)
            for key, value in matches:
                results[key] = value
                
        elif mode == AnalysisMode.FAST_VARIANT:
            # 快速变异模式：字段简化（9项），含特有标记v-win
            pattern = r'([a-zA-Z0-9\-_]+)\|([0-9.]+)'
            matches = re.findall(pattern, results_str)
            for key, value in matches:
                results[key] = value
                
        else:
            # 未知模式：使用通用解析
            pattern = r'([a-zA-Z0-9\-_]+)\|([0-9.]+)'
            matches = re.findall(pattern, results_str)
            for key, value in matches:
                results[key] = value
        
        return results

    @staticmethod
    def get_mode_description(mode):
        """获取模式描述"""
        descriptions = {
            'NORMAL': {
                'name': '常规模式',
                'description': '仅基础组分（7项），不包含变异筛查字段（如A2、HbS）',
                'typical_fields': ['HbA1a', 'HbA1b', 'HbF', 'L-A1c', 'HbA1c', 'HbA0', 'eAG']
            },
            'VARIANT_THAL': {
                'name': '变异/地贫模式',
                'description': '扩展至14项，新增A2、HbE/D/S/C等关键变异指标',
                'typical_fields': ['HbA1a', 'HbA1b', 'HbF', 'L-A1c', 'HbA1c', 'p3', 'HbA0', 'A2', 'HbE', 'HbD', 'HbS', 'HbC', 'eAG']
            },
            'FAST_VARIANT': {
                'name': '快速变异模式',
                'description': '字段简化（9项），但含特有标记v-win（快速识别变异窗口）',
                'typical_fields': ['HbA1a', 'HbA1b', 'HbF', 'L-A1c', 'HbA1c', 'p3', 'HbA0', 'v-win', 'eAG']
            },
            'UNKNOWN': {
                'name': '未知模式',
                'description': '无法识别的分析模式',
                'typical_fields': []
            }
        }
        # 使用枚举的名称作为键
        mode_name = mode.name if hasattr(mode, 'name') else 'UNKNOWN'
        return descriptions.get(mode_name, descriptions['UNKNOWN'])

    @staticmethod
    def parse_message(data):
        # 解析TRANSMIT消息
        if b'<TRANSMIT>' not in data:
            return None

        message = {
            'protocol': 'CUSTOM_LIS',
            'machine_model': None,
            'machine_id': None,
            'sample_info': {},
            'results': {},
            'image': {},
            'analysis_mode': AnalysisMode.UNKNOWN,
            'mode_info': {},
            'raw': data.decode('utf-8', errors='ignore'),
            'receive_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]  # 精确到毫秒
        }

        # 提取机器信息
        machine_match = re.search(r'<M>(.*?)<I>', message['raw'])
        if machine_match:
            machine_parts = machine_match.group(1).split('|')
            if len(machine_parts) >= 2:
                message['machine_model'] = machine_parts[0]
                message['machine_id'] = machine_parts[1]

        # 提取样本信息
        sample_match = re.search(r'<I>(.*?)</I>', message['raw'])
        if sample_match:
            sample_parts = sample_match.group(1).split('|')
            if sample_parts[0] == 'sample':
                # LD-560/LD-600格式
                if len(sample_parts) >= 6:
                    message['sample_info'] = {
                        'sample_type': sample_parts[0],
                        'datetime': sample_parts[1],
                        'sample_no': sample_parts[2],
                        'sample_id': sample_parts[3],
                        'rack_no': sample_parts[4] if len(sample_parts) > 6 else None,
                        'position': sample_parts[5] if len(sample_parts) > 6 else sample_parts[4],
                        'sample_category': sample_parts[6] if len(sample_parts) > 6 else sample_parts[5]
                    }
            else:
                # LD-100格式
                if len(sample_parts) >= 2:
                    message['sample_info'] = {
                        'datetime': sample_parts[0],
                        'sample_id': sample_parts[1]
                    }

        # 提取结果数据并检测模式
        results_match = re.search(r'<R>(.*?)</R>', message['raw'])
        if results_match:
            results_str = results_match.group(1)
            
            # 检测分析模式
            mode, mode_name = CustomLISParser.detect_analysis_mode(results_str)
            message['analysis_mode'] = mode
            message['mode_info'] = CustomLISParser.get_mode_description(mode)
            
            # 根据模式解析结果
            if message['machine_model'] == 'LD100':
                # LD-100特殊格式处理
                parts = results_str.split('|')
                if len(parts) >= 2:
                    message['results']['HbA1c'] = parts[1] if len(parts) > 2 else parts[0]
                    message['results']['reagent_batch'] = parts[2] if len(parts) > 2 else None
            else:
                # 根据检测到的模式解析结果
                message['results'] = CustomLISParser.parse_results_by_mode(results_str, mode)

        # 提取图片信息
        image_match = re.search(r'<IMAGE>(.*?)</IMAGE>', message['raw'], re.DOTALL)
        if image_match:
            image_content = image_match.group(1)
            
            # 提取图片名称
            name_match = re.search(r'<NAME>(.*?)</NAME>', image_content)
            if name_match:
                message['image']['filename'] = name_match.group(1)
            
            # 提取图片大小
            size_match = re.search(r'<SIZE>(.*?)</SIZE>', image_content)
            if size_match:
                message['image']['size'] = int(size_match.group(1))
            
            # 提取图片数据
            data_match = re.search(r'<DATA>(.*?)</DATA>', image_content, re.DOTALL)
            if data_match:
                image_data = data_match.group(1).strip()
                message['image']['data'] = image_data
                message['image']['data_length'] = len(image_data)
                
                # 尝试保存图片
                if message['image']['filename'] and message['image']['data']:
                    try:
                        logger.debug(f"调试：图片数据前20字符: {image_data[:20]}")
                        logger.debug(f"调试：图片数据长度: {len(image_data)}")
                        
                        # 自动检测格式并保存图片
                        save_result = ImageProcessor.detect_and_save_image(
                            image_data, 
                            message['image']['filename']
                        )
                        
                        # 更新图片信息
                        message['image'].update(save_result)
                        
                        if save_result['saved']:
                            logger.info(f"调试：图片保存成功，路径: {save_result['path']}")
                        else:
                            logger.error(f"调试：图片保存失败: {save_result.get('error', '未知错误')}")
                            
                    except Exception as e:
                        message['image']['saved'] = False
                        message['image']['error'] = str(e)
                        logger.error(f"调试：图片处理异常: {e}")

        return message

    @staticmethod
    def create_ack():
        """创建自定义协议的ACK响应（如果需要）"""
        # 自定义协议通常是单向的，不需要ACK
        return None

class ProtocolProcessor:
    """协议处理器"""

    @staticmethod
    def identify_protocol(data):
        if b'<TRANSMIT>' in data:
            return ProtocolType.CUSTOM_LIS
        return ProtocolType.UNKNOWN

    @staticmethod
    def process_data(data):
        protocol_type = ProtocolProcessor.identify_protocol(data)

        if protocol_type == ProtocolType.CUSTOM_LIS:
            message = CustomLISParser.parse_message(data)
            ack = CustomLISParser.create_ack()
            return message, ack

        return None, None

class TCPClient:
    """TCP客户端 - 使用Queue和多线程优化"""

    def __init__(self, host='127.0.0.1', port=5000):
        self.host = host
        self.port = port
        self.client_socket = None
        self.running = False
        self.connected = False
        self.last_heartbeat = time.time()
        self.message_count = 0  # 消息计数器
        self.reconnect_interval = 5  # 重连间隔（秒）
        self.buffer = b''  # 数据缓冲区
        self.max_buffer_size = 10 * 1024 * 1024  # 最大缓冲区大小（10MB）
        self.reconnect_count = 0  # 重连次数
        self.max_reconnect_attempts = 10  # 最大重连尝试次数
        
        # 新增：重连和初始化相关
        self.last_message_id = None  # 最后接收的消息ID
        self.reconnect_callbacks = []  # 重连成功后的回调函数列表
        self.initialization_commands = []  # 初始化命令列表
        self.subscription_commands = []  # 订阅命令列表
        self.old_socket = None  # 旧socket引用
        self.old_threads = []  # 旧线程引用列表
        
        # 新增：Queue和多线程相关
        self.data_queue = Queue(maxsize=1000)  # 数据队列，最大1000条消息
        self.receive_thread = None
        self.process_thread = None
        self.receive_running = False
        self.process_running = False
        
        # 初始化默认命令
        self._init_default_commands()
        
        # 流量控制参数
        self.max_queue_size = 1000  # 最大队列大小
        self.queue_warning_threshold = 800  # 队列警告阈值
        self.backpressure_delay = 0.1  # 背压延迟（秒）
        self.last_queue_warning = 0  # 上次队列警告时间
        
        # 性能监控
        self.receive_rate = 0  # 接收速率（消息/秒）
        self.process_rate = 0  # 处理速率（消息/秒）
        self.last_receive_count = 0
        self.last_process_count = 0
        self.last_rate_check = time.time()
    
    def _init_default_commands(self):
        """初始化默认的命令列表"""
        # 初始化命令（握手、认证等）
        self.initialization_commands = [
            b'<HANDSHAKE><VERSION>1.0</VERSION><CLIENT>LIS_CLIENT</CLIENT></HANDSHAKE>',
            b'<AUTH><USERNAME>default</USERNAME><PASSWORD>default</PASSWORD></AUTH>'
        ]
        
        # 订阅命令（请求数据流等）
        self.subscription_commands = [
            b'<SUBSCRIBE><TYPE>ALL</TYPE><LAST_ID>0</LAST_ID></SUBSCRIBE>',
            b'<REQUEST><TYPE>REPLAY</TYPE><COUNT>10</COUNT></REQUEST>'
        ]
    
    def add_reconnect_callback(self, callback):
        """添加重连成功后的回调函数"""
        if callback not in self.reconnect_callbacks:
            self.reconnect_callbacks.append(callback)
            logger.info(f"已添加重连回调函数: {callback.__name__ if hasattr(callback, '__name__') else 'unknown'}")
    
    def remove_reconnect_callback(self, callback):
        """移除重连回调函数"""
        if callback in self.reconnect_callbacks:
            self.reconnect_callbacks.remove(callback)
            logger.info(f"已移除重连回调函数: {callback.__name__ if hasattr(callback, '__name__') else 'unknown'}")
    
    def add_initialization_command(self, command):
        """添加初始化命令"""
        if command not in self.initialization_commands:
            self.initialization_commands.append(command)
            logger.info(f"已添加初始化命令: {command}")
    
    def add_subscription_command(self, command):
        """添加订阅命令"""
        if command not in self.subscription_commands:
            self.subscription_commands.append(command)
            logger.info(f"已添加订阅命令: {command}")
    
    def update_last_message_id(self, message_id):
        """更新最后接收的消息ID"""
        self.last_message_id = message_id
        logger.debug(f"更新最后消息ID: {message_id}")
    
    def _build_subscription_with_last_id(self):
        """构建包含最后消息ID的订阅命令"""
        if self.last_message_id is not None:
            # 更新订阅命令中的LAST_ID
            for i, cmd in enumerate(self.subscription_commands):
                if b'<LAST_ID>' in cmd:
                    # 替换LAST_ID值
                    old_cmd = cmd
                    new_cmd = re.sub(rb'<LAST_ID>\d+</LAST_ID>', 
                                   f'<LAST_ID>{self.last_message_id}</LAST_ID>'.encode(), 
                                   cmd)
                    self.subscription_commands[i] = new_cmd
                    logger.info(f"更新订阅命令LAST_ID: {old_cmd} -> {new_cmd}")
                    break

    def connect(self):
        """连接到服务器"""
        try:
            # 保存旧socket引用
            if self.client_socket:
                self.old_socket = self.client_socket
                logger.info("保存旧socket引用，准备清理")
            
            # 创建新socket
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)  # 增加接收缓冲区
            self.client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)  # 启用保活
            self.client_socket.settimeout(1.0)  # 设置超时
            self.client_socket.connect((self.host, self.port))
            
            # 连接成功
            self.connected = True
            self.reconnect_count = 0  # 重置重连计数
            logger.info(f"TCP客户端已连接到服务器 {self.host}:{self.port}")
            
            # 如果是重连，执行重连后的初始化
            if self.old_socket is not None:
                self._on_reconnect_success()
            
            return True
        except Exception as e:
            logger.error(f"TCP连接失败: {e}")
            self.connected = False
            return False
    
    def _on_reconnect_success(self):
        """重连成功后的处理"""
        try:
            logger.info("重连成功，开始执行初始化流程...")
            
            # 更新订阅命令中的LAST_ID
            self._build_subscription_with_last_id()
            
            # 发送初始化命令
            self._send_initialization_commands()
            
            # 发送订阅命令
            self._send_subscription_commands()
            
            # 执行重连回调函数
            self._execute_reconnect_callbacks()
            
            # 清理旧连接
            self._cleanup_old_connection()
            
            logger.info("重连初始化流程完成")
            
        except Exception as e:
            logger.error(f"重连初始化流程失败: {e}")
    
    def _send_initialization_commands(self):
        """发送初始化命令"""
        try:
            for i, command in enumerate(self.initialization_commands):
                if self.connected and self.client_socket:
                    self.client_socket.sendall(command)
                    logger.info(f"已发送初始化命令 {i+1}: {command}")
                    time.sleep(0.1)  # 命令间隔
                else:
                    logger.warning("连接已断开，无法发送初始化命令")
                    break
        except Exception as e:
            logger.error(f"发送初始化命令失败: {e}")
    
    def _send_subscription_commands(self):
        """发送订阅命令"""
        try:
            for i, command in enumerate(self.subscription_commands):
                if self.connected and self.client_socket:
                    self.client_socket.sendall(command)
                    logger.info(f"已发送订阅命令 {i+1}: {command}")
                    time.sleep(0.1)  # 命令间隔
                else:
                    logger.warning("连接已断开，无法发送订阅命令")
                    break
        except Exception as e:
            logger.error(f"发送订阅命令失败: {e}")
    
    def _execute_reconnect_callbacks(self):
        """执行重连回调函数"""
        try:
            if self.reconnect_callbacks:
                logger.info(f"执行 {len(self.reconnect_callbacks)} 个重连回调函数")
                for callback in self.reconnect_callbacks:
                    try:
                        callback()
                        logger.debug(f"重连回调函数执行成功: {callback.__name__ if hasattr(callback, '__name__') else 'unknown'}")
                    except Exception as e:
                        logger.error(f"重连回调函数执行失败: {e}")
            else:
                logger.debug("没有注册的重连回调函数")
        except Exception as e:
            logger.error(f"执行重连回调函数失败: {e}")
    
    def _cleanup_old_connection(self):
        """清理旧连接"""
        try:
            if self.old_socket:
                logger.info("开始清理旧连接...")
                
                # 关闭旧socket
                try:
                    self.old_socket.close()
                    logger.info("旧socket已关闭")
                except Exception as e:
                    logger.warning(f"关闭旧socket失败: {e}")
                
                # 清理旧线程
                if self.old_threads:
                    for thread in self.old_threads:
                        try:
                            if thread.is_alive():
                                thread.join(timeout=1.0)
                                logger.debug(f"旧线程已清理: {thread.name if hasattr(thread, 'name') else 'unknown'}")
                        except Exception as e:
                            logger.warning(f"清理旧线程失败: {e}")
                    
                    self.old_threads.clear()
                    logger.info("旧线程已清理完成")
                
                # 清空旧socket引用
                self.old_socket = None
                logger.info("旧连接清理完成")
            else:
                logger.debug("没有旧连接需要清理")
                
        except Exception as e:
            logger.error(f"清理旧连接失败: {e}")

    def disconnect(self):
        """断开连接"""
        try:
            logger.info("开始断开TCP连接...")
            
            # 标记连接状态
            self.connected = False
            
            # 保存旧socket和线程引用
            if self.client_socket:
                self.old_socket = self.client_socket
                self.old_threads = []
                
                # 保存当前线程引用
                if self.receive_thread and self.receive_thread.is_alive():
                    self.old_threads.append(self.receive_thread)
                if self.process_thread and self.process_thread.is_alive():
                    self.old_threads.append(self.process_thread)
                
                # 清空当前引用
                self.client_socket = None
                self.receive_thread = None
                self.process_thread = None
            
            # 清空缓冲区
            self.buffer = b''
            
            # 清理旧连接
            self._cleanup_old_connection()
            
            logger.info("TCP客户端已断开连接")
            
        except Exception as e:
            logger.error(f"断开连接失败: {e}")

    def handle_connection_error(self, error):
        """处理连接错误"""
        error_str = str(error)
        if "10053" in error_str or "10054" in error_str or "10061" in error_str:
            # Windows连接错误：连接被重置、连接被拒绝等
            logger.info(f"检测到连接中断: {error_str}")
            self.connected = False
            return True
        elif "Connection reset" in error_str or "Broken pipe" in error_str:
            # Unix/Linux连接错误
            logger.info(f"检测到连接重置: {error_str}")
            self.connected = False
            return True
        else:
            logger.error(f"未知连接错误: {error_str}")
            return False

    def receive_data_thread(self):
        """接收数据线程"""
        logger.info("TCP接收数据线程已启动")
        self.receive_running = True
        
        while self.receive_running and self.running:
            if not self.connected:
                time.sleep(0.1)
                continue
                
            try:
                # 接收数据
                data = self.client_socket.recv(4096)
                if not data:
                    logger.info("服务器关闭了连接")
                    self.connected = False
                    break

                # 添加到缓冲区
                self.buffer += data
                
                # 防止缓冲区过大
                if len(self.buffer) > self.max_buffer_size:
                    logger.warning(f"警告：缓冲区过大 ({len(self.buffer)} bytes)，清空缓冲区")
                    self.buffer = b''
                    continue
                
                # 检查是否有完整消息
                if b'<TRANSMIT>' in self.buffer and b'</TRANSMIT>' in self.buffer:
                    self.extract_and_queue_messages()


            except socket.timeout:
                # 超时，继续循环
                continue
            except ConnectionResetError as e:
                logger.error(f"连接被重置: {e}")
                self.connected = False
                break
            except Exception as e:
                if self.handle_connection_error(e):
                    break
                else:
                    logger.error(f"接收数据错误: {e}")
                    time.sleep(0.1)
        
        logger.info("TCP接收数据线程已停止")

    def extract_and_queue_messages(self):
        """提取完整消息并加入队列"""
        extracted_count = 0
        
        while b'<TRANSMIT>' in self.buffer and b'</TRANSMIT>' in self.buffer:
            start_idx = self.buffer.find(b'<TRANSMIT>')
            end_idx = self.buffer.find(b'</TRANSMIT>', start_idx)
            
            if end_idx == -1:
                # 没有找到结束标记，等待更多数据
                break
                
            # 提取完整消息
            message_end = end_idx + len(b'</TRANSMIT>')
            message_data = self.buffer[start_idx:message_end]
            
            # 检查队列大小，实施背压控制
            if self.data_queue.qsize() >= self.max_queue_size:
                current_time = time.time()
                if current_time - self.last_queue_warning > 5:  # 每5秒最多警告一次
                    logger.warning(f"队列已满 ({self.data_queue.qsize()}/{self.max_queue_size})，暂停接收")
                    self.last_queue_warning = current_time
                time.sleep(self.backpressure_delay)
                break
            
            # 将消息加入队列
            try:
                self.data_queue.put_nowait(message_data)
                extracted_count += 1
                self.last_receive_count += 1
            except Full:
                logger.warning("队列已满，丢弃消息")
                break
            
            # 移除已提取的消息
            self.buffer = self.buffer[message_end:]
        
        if extracted_count > 0:
            logger.debug(f"提取了 {extracted_count} 条消息到队列，缓冲区剩余 {len(self.buffer)} 字节")

    def process_data_thread(self):
        """处理数据线程"""
        logger.info("TCP处理数据线程已启动")
        self.process_running = True
        
        while self.process_running and self.running:
            try:
                # 从队列获取消息，设置超时避免阻塞
                try:
                    message_data = self.data_queue.get(timeout=1.0)
                except Empty:
                    # 队列为空，继续循环
                    continue
                
                # 处理消息
                message, ack = ProtocolProcessor.process_data(message_data)
                if message:
                    self.message_count += 1
                    self.last_process_count += 1
                    logger.info(f"处理第 {self.message_count} 条 {message['protocol']} 协议消息")
                    
                    # 发送ACK（如果需要）
                    if ack and self.connected:
                        try:
                            self.client_socket.sendall(ack)
                            logger.debug("已发送ACK响应")
                        except Exception as e:
                            if self.handle_connection_error(e):
                                break
                            else:
                                logger.error(f"发送ACK失败: {e}")
                
                # 标记任务完成
                self.data_queue.task_done()
                
            except Exception as e:
                logger.error(f"处理数据错误: {e}")
                time.sleep(0.1)
        
        logger.info("TCP处理数据线程已停止")

    def update_performance_metrics(self):
        """更新性能指标"""
        current_time = time.time()
        if current_time - self.last_rate_check >= 5:  # 每5秒更新一次
            time_diff = current_time - self.last_rate_check
            
            self.receive_rate = self.last_receive_count / time_diff
            self.process_rate = self.last_process_count / time_diff
            
            # 记录性能指标
            queue_size = self.data_queue.qsize()
            logger.info(f"性能指标 - 接收速率: {self.receive_rate:.2f} msg/s, "
                       f"处理速率: {self.process_rate:.2f} msg/s, "
                       f"队列大小: {queue_size}/{self.max_queue_size}")
            
            # 检查队列状态
            if queue_size > self.queue_warning_threshold:
                logger.warning(f"队列使用率较高: {queue_size}/{self.max_queue_size} "
                             f"({queue_size/self.max_queue_size*100:.1f}%)")
            
            # 重置计数器
            self.last_receive_count = 0
            self.last_process_count = 0
            self.last_rate_check = current_time

    def start(self):
        """启动客户端"""
        self.running = True
        logger.info(f"TCP客户端启动，目标服务器 {self.host}:{self.port}")

        # 启动接收数据线程
        self.receive_thread = threading.Thread(target=self.receive_data_thread, name="TCP_Receive")
        self.receive_thread.daemon = True
        self.receive_thread.start()

        # 启动处理数据线程
        self.process_thread = threading.Thread(target=self.process_data_thread, name="TCP_Process")
        self.process_thread.daemon = True
        self.process_thread.start()

        # 启动心跳检测线程
        heartbeat_thread = threading.Thread(target=self.check_heartbeat, name="TCP_Heartbeat")
        heartbeat_thread.daemon = True
        heartbeat_thread.start()

        # 启动重连线程
        reconnect_thread = threading.Thread(target=self.reconnect_loop, name="TCP_Reconnect")
        reconnect_thread.daemon = True
        reconnect_thread.start()

        # 主循环 - 监控线程状态和性能
        while self.running:
            try:
                # 检查线程状态
                if (self.receive_thread and not self.receive_thread.is_alive()) or \
                   (self.process_thread and not self.process_thread.is_alive()):
                    logger.error("检测到工作线程异常退出")
                    break
                
                # 更新性能指标
                self.update_performance_metrics()
                
                # 短暂休眠
                time.sleep(1)
                
            except Exception as e:
                logger.error(f"主循环错误: {e}")
                time.sleep(1)

    def reconnect_loop(self):
        """重连循环"""
        while self.running:
            if not self.connected:
                self.reconnect_count += 1
                if self.reconnect_count <= self.max_reconnect_attempts:
                    logger.info(f"尝试重新连接到服务器 {self.host}:{self.port}... (第{self.reconnect_count}次)")
                    if self.connect():
                        logger.info("重连成功")
                        self.reconnect_count = 0  # 重置重连计数
                    else:
                        logger.error(f"重连失败，{self.reconnect_interval}秒后重试")
                        time.sleep(self.reconnect_interval)
                else:
                    logger.error(f"重连失败次数过多({self.reconnect_count}次)，停止重连")
                    self.running = False
                    break
            else:
                time.sleep(1)

    def check_heartbeat(self):
        """心跳检测线程"""
        while self.running:
            current_time = time.time()
            if self.connected and current_time - self.last_heartbeat >= 30:
                logger.info("心跳检测：发送心跳包...")
                try:
                    # 发送心跳包
                    heartbeat_data = b'HEARTBEAT'
                    self.client_socket.sendall(heartbeat_data)
                    self.last_heartbeat = current_time
                except Exception as e:
                    if self.handle_connection_error(e):
                        continue
                    else:
                        logger.error(f"心跳发送失败: {e}")
                        self.connected = False
            time.sleep(30)

    def stop(self):
        """停止客户端"""
        logger.info("正在停止TCP客户端...")
        self.running = False
        self.receive_running = False
        self.process_running = False
        
        # 等待线程结束
        if self.receive_thread and self.receive_thread.is_alive():
            logger.info("等待接收线程结束...")
            self.receive_thread.join(timeout=5)
            if self.receive_thread.is_alive():
                logger.warning("接收线程未能在5秒内结束")
        
        if self.process_thread and self.process_thread.is_alive():
            logger.info("等待处理线程结束...")
            self.process_thread.join(timeout=5)
            if self.process_thread.is_alive():
                logger.warning("处理线程未能在5秒内结束")
        
        # 清空队列
        while not self.data_queue.empty():
            try:
                self.data_queue.get_nowait()
                self.data_queue.task_done()
            except Empty:
                break
        
        # 断开连接并清理
        self.disconnect()
        
        logger.info(f"TCP客户端已停止，共处理 {self.message_count} 条消息")

    def test_connection(self):
        """测试连接"""
        try:
            if self.connect():
                self.disconnect()
                return True
            return False
        except Exception as e:
            logger.error(f"测试TCP连接失败: {e}")
            return False

    def write(self, data: bytes) -> bool:
        """发送数据"""
        try:
            if self.connected and self.client_socket:
                self.client_socket.sendall(data)
                logger.debug(f"TCP客户端发送数据: {len(data)} 字节")
                return True
            else:
                logger.error("TCP客户端未连接，无法发送数据")
                return False
        except Exception as e:
            logger.error(f"TCP客户端发送数据失败: {e}")
            return False

    def get_queue_status(self):
        """获取队列状态"""
        return {
            'queue_size': self.data_queue.qsize(),
            'max_queue_size': self.max_queue_size,
            'receive_rate': self.receive_rate,
            'process_rate': self.process_rate,
            'buffer_size': len(self.buffer),
            'max_buffer_size': self.max_buffer_size
        }

# 保留原有的方法用于向后兼容
    def receive_complete_data(self):
        """接收完整的数据包 - 保留用于向后兼容"""
        logger.warning("receive_complete_data方法已弃用，请使用新的多线程架构")
        return True

    def process_buffer(self):
        """处理缓冲区中的完整消息 - 保留用于向后兼容"""
        logger.warning("process_buffer方法已弃用，请使用新的多线程架构")
        return 0

class TCPCommunicationThread(QThread):
    """TCP通信线程"""
    
    # 定义信号
    message_processed = pyqtSignal(dict)  # 消息处理完成信号
    connection_status_changed = pyqtSignal(bool)  # 连接状态变化信号
    error_occurred = pyqtSignal(str)  # 错误信号
    queue_status_updated = pyqtSignal(dict)  # 队列状态更新信号
    
    def __init__(self, tcp_client: TCPClient, data_callback: Callable = None, comm_manager=None):
        super().__init__()
        self.tcp_client = tcp_client
        self.data_callback = data_callback
        self.comm_manager = comm_manager
        self.running = False
        
        # 重写TCP客户端的消息处理回调
        self.original_process_data_thread = self.tcp_client.process_data_thread
        self.tcp_client.process_data_thread = self.process_data_thread_with_callback
        
    def process_data_thread_with_callback(self):
        """带回调的数据处理线程"""
        logger.info("TCP处理数据线程已启动（带回调）")
        self.tcp_client.process_running = True
        
        while self.tcp_client.process_running and self.tcp_client.running:
            try:
                # 从队列获取消息，设置超时避免阻塞
                try:
                    message_data = self.tcp_client.data_queue.get(timeout=1.0)
                except Empty:
                    # 队列为空，继续循环
                    continue
                
                # 处理消息
                message, ack = ProtocolProcessor.process_data(message_data)
                if message:
                    self.tcp_client.message_count += 1
                    self.tcp_client.last_process_count += 1
                    logger.info(f"TCP处理第 {self.tcp_client.message_count} 条 {message['protocol']} 协议消息")
                    
                    # 发送信号
                    self.message_processed.emit(message)
                    
                    # 调用回调函数
                    if self.data_callback:
                        try:
                            self.data_callback(message)
                        except Exception as e:
                            logger.error(f"TCP数据回调函数执行失败: {e}")
                            self.error_occurred.emit(f"数据回调函数执行失败: {e}")
                    
                    # 发送ACK（如果需要）
                    if ack and self.tcp_client.connected:
                        try:
                            self.tcp_client.client_socket.sendall(ack)
                            logger.debug("已发送ACK响应")
                        except Exception as e:
                            if self.tcp_client.handle_connection_error(e):
                                break
                            else:
                                logger.error(f"发送ACK失败: {e}")
                
                # 标记任务完成
                self.tcp_client.data_queue.task_done()
                
                # 发送队列状态更新信号
                self.queue_status_updated.emit(self.tcp_client.get_queue_status())
                
            except Exception as e:
                logger.error(f"处理数据错误: {e}")
                time.sleep(0.1)
        
        logger.info("TCP处理数据线程已停止（带回调）")
    
    def run(self):
        """运行线程"""
        self.running = True
        logger.info("TCP通信线程已启动")
        
        try:
            # 启动TCP客户端
            self.tcp_client.start()
        except Exception as e:
            logger.error(f"TCP通信线程错误: {e}")
            self.error_occurred.emit(f"TCP通信线程错误: {e}")
        finally:
            self.running = False
            logger.info("TCP通信线程已停止")
    
    def stop(self):
        """停止线程"""
        self.running = False
        if self.tcp_client:
            self.tcp_client.stop()
        self.wait() 